import React, { useEffect, useRef, useState } from 'react'
import './index.css'
import { verifySudoku } from './verify'

// 这是每个格子的数据类型
interface IData {
  value: number | string
  canichange: boolean
  selected: boolean
}

// 这是Grid组件props的类型
interface IProps {
  data: IData[]
  onChange: Function
}

function Grid(props: IProps) {
  const [data, setData] = useState(props.data)

  const curSelected = useRef<number | null>(null)

  const { onChange } = props

  const tabBox = (i: number) => {
    if (curSelected.current !== null) {
      data[curSelected.current].selected = false
    }
    curSelected.current = i
    data[i].selected = true
    setData([...data])
    onChange({
      idx: i,
      val: data[i],
    })
  }

  return (
    <div className="mid-box">
      {data.map((item, i) => (
        <div
          key={i}
          className={item.selected ? 'box active' : 'box'}
          onClick={() => {
            tabBox(i)
          }}
        >
          {item.value}
        </div>
      ))}
    </div>
  )
}

function Shudu() {
  // 初始数据
  const data = [
    [0, 2, 0, 0, 0, 6, 0, 7, 0],
    [4, 0, 9, 0, 5, 0, 0, 8, 3],
    [1, 0, 0, 0, 8, 9, 0, 2, 4],
    [7, 1, 0, 0, 0, 0, 0, 0, 0],
    [5, 0, 0, 0, 9, 0, 0, 4, 0],
    [0, 0, 0, 2, 0, 0, 0, 0, 7],
    [0, 6, 0, 0, 0, 7, 3, 4, 0],
    [0, 0, 0, 3, 0, 0, 0, 0, 5],
    [0, 0, 0, 8, 0, 1, 0, 6, 0],
  ]
  const curPoint = useRef<null | number[]>(null)

  useEffect(() => {
    if (window.localStorage.getItem('sudoku')) {
      let oldData = JSON.parse(
        window.localStorage.getItem('sudoku') as string
      )
      setDataSource(oldData)
      for (let i = 0; i < 9; i++) {
        for (let j = 0; j < 9; j++) {
          oldData[i][j].selected && (curPoint.current = [i, j])
        }
      }
    }
  }, [])

  let initData = data.map((v) => {
    return v.map((item) => {
      return {
        value: item ? item : '',
        canichange: !item,
        selected: false,
      }
    })
  })

  const [dataSource, setDataSource] = useState<Array<IData[]>>(initData)

  const getBoxPoint = (x: number, y: number) => {
    if (!dataSource[x][y].canichange) return

    if (curPoint.current !== null) {
      const [n, m] = curPoint.current
      dataSource[n][m].selected = false
    }
    dataSource[x][y].selected = true
    curPoint.current = [x, y]
    setDataSource([...dataSource])
  }

  const clearBox = () => {
    if (curPoint.current) {
      const [n, m] = curPoint.current
      dataSource[n][m].value = ''
      setDataSource([...dataSource])
      saveData()
    }
  }

  const checkIt = () => {
    const res = verifySudoku(dataSource)
    console.log(res)
  }

  const gridChange = (data: { idx: number; val: IData }) => {
    if (curPoint.current) {
      const [n, m] = curPoint.current
      dataSource[n][m].value = data.val.value
      setDataSource([...dataSource])
      saveData()
    }
  }

  const saveData = () => {
    window.localStorage.setItem('sudoku', JSON.stringify(dataSource))
  }

  let arrBtn = [1, 2, 3, 4, 5, 6, 7, 8, 9].map((item) => {
    return {
      value: item ? item : '',
      canichange: !item,
      selected: false,
    }
  })

  return (
    <div>
      <div className="content">
        {dataSource.map((data, idx) => (
          <div key={idx} className="mid-box">
            {data.map((item, i) => (
              <div
                key={i}
                className={item.selected ? 'box active' : 'box'}
                onClick={() => {
                  getBoxPoint(idx, i)
                }}
              >
                {item.value}
              </div>
            ))}
          </div>
        ))}
      </div>
      <div className="btn-number">
        <Grid onChange={gridChange} data={arrBtn} />
      </div>

      <div className="btn-box">
        <button onClick={clearBox}>清除</button>
        <button onClick={checkIt}>验证</button>
      </div>
    </div>
  )
}

export default Shudu
